package org.fableStudios.tetris;

import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//http://www.javamex.com/tutorials/random_numbers/numerical_recipes.shtml
public class HighQualityRandom extends Random {
	private static final long serialVersionUID = -2654986030502941885L;
	private Lock l=new ReentrantLock();
	private long u;
	private long v=4101842887655102017L;
	private long w=1;
	
	public HighQualityRandom() {
		this(System.nanoTime());
	}

	public HighQualityRandom(long seed) {
		l.lock();
		{
			u=seed^v;
			nextLong();
			v=u;
			nextLong();
			w=v;
			nextLong();
		}
		l.unlock();
	}
	
	public long nextLong() {
		l.lock();
		try {
			u=u*2862933555777941757L+7046029254386353087L;
			v^=v>>>17;
			v^=v<<31;
			v^=v>>>8;
			w=4294957665L*(w&0xFFFFFFFF)+(w>>>32);
			long x=u^(u<<21);
			x^=x>>>35;
			x^=x<<4;
			long ret=(x+v)^w;
			return ret;
		} finally {
			l.unlock();
		}
	}
	
	protected int next(int bits) {
		return (int)(nextLong()>>>64-bits);
	}
	
	@Override
	public int nextInt(int limit) {
		long l=nextLong();
		int i=(int)(l/1000);
		if(i<0)i=-i;
		return i%limit;
	}
}
